package indzcraft.ui;
import indzcraft.calc.IndzCraftCalc;
import indzcraft.calc.Weapon;
import indzcraft.loader.BaseStats;
import indzcraft.loader.Enchant;
import indzcraft.loader.Gem;
import indzcraft.loader.IndzCraftLoader;
import indzcraft.loader.ItemEquiped;
import indzcraft.loader.RaceDB;
import indzcraft.ranking.Database;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.KeyEvent;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.imageio.ImageIO;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableRowSorter;

import org.json.JSONException;

import com.googlecode.charts4j.AxisLabelsFactory;
import com.googlecode.charts4j.Data;
import com.googlecode.charts4j.GCharts;
import com.googlecode.charts4j.LineChart;
import com.googlecode.charts4j.Plot;
import com.googlecode.charts4j.Plots;
import com.googlecode.charts4j.Color;


@SuppressWarnings("serial")
public class IndzCraftUI extends JFrame implements ActionListener,ItemListener{

	public static void main(String[] args){
		new IndzCraftUI();
	}
	private IndzCraftLoader loader = new IndzCraftLoader();
	Database db = new Database(loader);
	IndzCraftCalc calc = null;
	Settings settings = new Settings();
	
	JMenuItem fromBattleNet;
	JMenuItem anItem;
	JButton go;
	JTextField realm;
	JTextField player;
	private JButton importItemIdButton;
	private JTextField importItemId;
	JDialog d = new JDialog();
	
	public ItemSlot[] itemSlots;
	public JPanel itemPanel = null;
	private JScrollPane sidePanel;
	
	public JButton dps_test = null;
	public JButton bSettings = null;
	
	private JLabel dps = null;
	private JTable tableEP = null;
	private JScrollPane scrollEP = null;
	private EnchantPanel enchantPanel;
	private ReforgePanel reforgePanel;
	private JButton autoReforge = null;
	
	private Log log = null;
	private List<Float> dpsHistory = new ArrayList<Float>();
	
	
	public IndzCraftUI(){
		settings.addPropertyChangeListener( new SettingsListener(this) );
		loader.setDatabase(db);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		//this.getContentPane().add(emptyLabel, BorderLayout.CENTER);
		this.setTitle("IndzCraft");
		this.setSize(1000,700);
		createMenu();
		
		this.setLayout(null);
		
		int itemSlotWidth = 140;
		int itemSlotHeight = 60;
		
		itemSlots = new ItemSlot[19];
		for(int i = 0;i < 8;i++){
			itemSlots[i] = new ItemSlot(this,i,null);
			itemSlots[i].setBounds(0, i*itemSlotHeight, itemSlotWidth, itemSlotHeight);
			add( itemSlots[i] );
		}
		
		for(int i = 8;i < 16;i++){
			itemSlots[i] = new ItemSlot(this,i,null);
			itemSlots[i].setBounds(itemSlotWidth*3, 0+(i-8)*itemSlotHeight, itemSlotWidth, itemSlotHeight);
			add( itemSlots[i] );
		}
		int i = 16;
		itemSlots[i] = new ItemSlot(this,i,null);
		itemSlots[i].setBounds(itemSlotWidth/2, 8*itemSlotHeight, itemSlotWidth, itemSlotHeight);
		add( itemSlots[i] );
		i = 17;
		itemSlots[i] = new ItemSlot(this,i,null);
		itemSlots[i].setBounds(itemSlotWidth/2+itemSlotWidth, 8*itemSlotHeight, itemSlotWidth, itemSlotHeight);
		add( itemSlots[i] );
		i = 18;
		itemSlots[i] = new ItemSlot(this,i,null);
		itemSlots[i].setBounds(itemSlotWidth/2+itemSlotWidth*2, 8*itemSlotHeight, itemSlotWidth, itemSlotHeight);
		add( itemSlots[i] );
		
		
		dps_test = new JButton("dps_test");
		dps_test.setBounds(itemSlotWidth, 0, 100, 30);
		dps_test.addActionListener(this);
		add (dps_test);
		
		bSettings = new JButton("Settings");
		bSettings.setBounds(itemSlotWidth+100, 0, 100, 30);
		bSettings.addActionListener(this);
		add (bSettings);
		
		sidePanel = new JScrollPane();
		sidePanel.setBounds(600, 0, 380, 430);
		sidePanel.getVerticalScrollBar().setUnitIncrement(20);
		//sidePanel.set
		add( sidePanel );
		
		dps = new JLabel();
		dps.setBounds(itemSlotWidth,30,100,30);
		add( dps );
		
		// ep table
		tableEP = new JTable(new MyTableModel());
		tableEP.setAutoCreateRowSorter(true);
		scrollEP = new JScrollPane(tableEP);
		tableEP.setFillsViewportHeight(true);
		scrollEP.setBounds(itemSlotWidth,60,200,300);
		add( scrollEP );
		
		autoReforge = new JButton("Auto Reforge");
		autoReforge.setBounds(400, 600, 100, 30);
		autoReforge.addActionListener(this);
		add (autoReforge);
		
		log = new Log();
		log.append("Test");
		log.append("Test3434");
		
		JScrollPane logPanel = new JScrollPane(log);
		logPanel.setBounds(600,430,380,200);
		logPanel.getVerticalScrollBar().setUnitIncrement(20);
		logPanel.setBorder(BorderFactory.createLineBorder(java.awt.Color.black));
		//sidePanel.set
		add( logPanel );
		
		this.setVisible(true);
	}
	
	public void setItemSlot(int slot,ItemEquiped item){
		itemSlots[slot].setItem(item);
		loader.getEquipment().put(Slot.possibleSlots[slot].getName(),item);
 	}
	public void setGemSlot(int slot,int gemSlot,Gem gem){
		itemSlots[slot].setGemSlot(gemSlot, gem);
 	}
	
	public void createMenu(){
		JMenuBar menuBar = new JMenuBar();
		JMenu menu = new JMenu("Import...");
		menu.setMnemonic(KeyEvent.VK_I);
		menuBar.add(menu);
		
		fromBattleNet = new JMenuItem("from Battle.net", KeyEvent.VK_T);
		fromBattleNet.setAccelerator(KeyStroke.getKeyStroke(
				KeyEvent.VK_1, ActionEvent.ALT_MASK));
		fromBattleNet.getAccessibleContext().setAccessibleDescription(
				"This doesn't really do anything");
		fromBattleNet.addActionListener(this);
		menu.add(fromBattleNet);
		
		anItem = new JMenuItem("an Item");
		anItem.getAccessibleContext().setAccessibleDescription(
		"This doesn't really do anything");
		anItem.addActionListener(this);
		menu.add(anItem);
		
		JMenu menu_professions = new JMenu("professions");
		menuBar.add(menu_professions);
		
		JCheckBoxMenuItem[] profession = new JCheckBoxMenuItem[8];
		profession[0] = new JCheckBoxMenuItem("Alchemy");
		menu_professions.add(profession[0]);
		profession[1] = new JCheckBoxMenuItem("Jewelcrafting");
		menu_professions.add(profession[1]);
		
		this.setJMenuBar(menuBar);
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		//System.out.println(e.getSource());
		if(e.getSource() == fromBattleNet){
			d = new JDialog();                   // nicht modal
			d.setLayout(null);
			d.setSize( 230, 100 );
			realm = new JTextField(50);
			realm.setBounds(0, 0, 100, 20);
			realm.setText("Gorgonnash");
			d.add( realm );
			player = new JTextField(50);
			player.setBounds(105, 0, 100, 20);
			player.setText("Indz");
			d.add( player );
			go = new JButton("Import");
			go.setBounds(0, 20, 100, 40);
			
			go.addActionListener(this);
			
			d.add( go );
			d.setVisible( true );
		}
		else if(e.getSource() == go){
			System.out.println("import of " + player.getText() + " " + realm.getText());
			try {	
				d.setVisible( false );
				loader.setDatabase(db);
				loader.load2(player.getText(),realm.getText(),"eu",true);
				BaseStats base = loader.getBase();
				//System.out.println("gearbuff0: " + base.getGearBuffs().get(0));
				calc = new IndzCraftCalc(loader, base);
				
				this.showItems();
				this.showStats();
			} catch (JSONException ex) {
				ex.printStackTrace();
			}
		}
		else if(e.getSource() == anItem){
			d = new JDialog();                   // nicht modal
			d.setLayout(null);
			d.setSize( 230, 100 );
			importItemId = new JTextField(50);
			importItemId.setBounds(0, 0, 100, 20);
			d.add( importItemId );
			importItemIdButton = new JButton("Import ItemId");
			importItemIdButton.setBounds(0, 20, 100, 40);
			
			importItemIdButton.addActionListener(this);
			
			d.add( importItemIdButton );
			d.setVisible( true );
		}
		else if(e.getSource() == importItemIdButton){
			System.out.println("import of itemId " + importItemId.getText());
			d.setVisible( false );
			String itemids = importItemId.getText();
			String[] items = itemids.split(",");
			System.out.println(items.length);
			for(int i = 0;i < items.length;i++){
				int id = Integer.parseInt(items[i]);
				db.get(id);
			}
		}
		else if(e.getSource() == dps_test){
			
			showStats();
			
			tableEP = new JTable();
			//tableEP.setAutoCreateRowSorter(true);
			tableEP.setFillsViewportHeight(true);
			TableRowSorter<MyTableModel> trs = new TableRowSorter<MyTableModel>(new MyTableModel());
			trs.toggleSortOrder(1);
			tableEP.setRowSorter(trs);
			trs.setSortsOnUpdates(true);
			scrollEP = new JScrollPane(tableEP);
			scrollEP.setBounds(400,300,200,300);
			repaint();
			//add( scrollEP );
		}
		else if(e.getSource() == bSettings){
			showSettingsPanel();
		}
		else if(e.getSource() == autoReforge){
			ReforgeTask task = new ReforgeTask(this);
			task.execute();
		}
	}

	public void showItems() {
		
		ItemEquiped item = loader.getEquipment().get("head");
		itemSlots[0].setItem(item);
		
		item = loader.getEquipment().get("neck");
		itemSlots[1].setItem(item);
		
		item = loader.getEquipment().get("shoulder");
		itemSlots[2].setItem(item);
		
		item = loader.getEquipment().get("back");
		itemSlots[3].setItem(item);
		
		item = loader.getEquipment().get("chest");
		itemSlots[4].setItem(item);
		
		item = loader.getEquipment().get("shirt");
		itemSlots[5].setItem(item);
		
		item = loader.getEquipment().get("tabard");
		itemSlots[6].setItem(item);
		
		item = loader.getEquipment().get("wrist");
		itemSlots[7].setItem(item);
		//
		item = loader.getEquipment().get("hands");
		itemSlots[8].setItem(item);
		
		item = loader.getEquipment().get("waist");
		itemSlots[9].setItem(item);
		
		item = loader.getEquipment().get("legs");
		itemSlots[10].setItem(item);
		
		item = loader.getEquipment().get("feet");
		itemSlots[11].setItem(item);
		
		item = loader.getEquipment().get("finger1");
		itemSlots[12].setItem(item);
		
		item = loader.getEquipment().get("finger2");
		itemSlots[13].setItem(item);
		
		item = loader.getEquipment().get("trinket1");
		itemSlots[14].setItem(item);
		
		item = loader.getEquipment().get("trinket2");
		itemSlots[15].setItem(item);
		//
		item = loader.getEquipment().get("mainHand");
		itemSlots[16].setItem(item);
		
		item = loader.getEquipment().get("offHand");
		itemSlots[17].setItem(item);
		
		item = loader.getEquipment().get("ranged");
		itemSlots[18].setItem(item);
	}

	@Override
	public void itemStateChanged(ItemEvent e) {
		// 
	}

	public IndzCraftLoader getLoader() {
		return loader;
	}

	public void showItemPanel(int slot) {
		itemPanel = new ItemPanel(this, slot);
		sidePanel.setViewportView(itemPanel);
	}
	
	public void showGemPanel(int slot,int gemSlot) {
		GemPanel gemPanel = new GemPanel(this, slot, gemSlot);
		sidePanel.setViewportView(gemPanel);
	}
	
	public void showSettingsPanel(){
		SettingsPanel settingsPanel = new SettingsPanel(this);
		sidePanel.setViewportView(settingsPanel);
	}

	public JScrollPane getSidePanel() {
		return sidePanel;
	}
	
	public IndzCraftCalc getCalc(){
		return calc;
	}
	
	class MyTableModel extends AbstractTableModel {
	    private String[] columnNames = {"name", "ep" };
	    //private Object[][] data = ...//same as before...

	    public int getColumnCount() {
	        return columnNames.length;
	    }

	    public int getRowCount() {
	        //return data.length;
	    	if(calc != null){
	    		return calc.getStatsEP().size();
	    	}
	    	return 0;
	    }

	    public String getColumnName(int col) {
	        return columnNames[col];
	    }

	    public Object getValueAt(int row, int col) {
	    	if(col == 0)
	        {
	            return calc.getStatsEP().keySet().toArray()[row];
	        }
	        return calc.getStatsEP().values().toArray()[row];
	    }

	    public Class<?> getColumnClass(int c) {
	        return getValueAt(0, c).getClass();
	    }
	}

	public void showStats() {
		BaseStats base = new BaseStats();
		base.setRace(loader.getBase().getRace());
		
		if(settings.getTalents() == 1){
			base.setTalents(loader.getBase().getTalents()[0],loader.getBase().getTalents()[1],loader.getBase().getTalents()[2]);
			base.setTalentsName(loader.getBase().getTalentsName());
			base.setGlyphs(loader.getBase().getGlyphs());
		}
		else if(settings.getTalents() == 2){
			base.setTalents(loader.getBase().getOffTalents()[0],loader.getBase().getOffTalents()[1],loader.getBase().getOffTalents()[2]);
			base.setTalentsName(loader.getBase().getOffTalentsName());
			
			base.setGlyphs(loader.getBase().getOffGlyphs());
		}
		
		ItemEquiped mhe = loader.getEquipment().get("mainHand");
		//mhe.getItemSubClass()
		String enchant = "";
		if(mhe.getEnchant() != null)
			enchant = mhe.getEnchant().getName();
		Weapon mh = new Weapon(mhe.getSpeed(),mhe.getDps(),mhe.getWeaponTypeName(),enchant);
		base.setMH(mh);
		ItemEquiped ohe = loader.getEquipment().get("offHand");
		enchant = "";
		if(ohe.getEnchant() != null)
			enchant = ohe.getEnchant().getName();
		Weapon oh = new Weapon(ohe.getSpeed(),ohe.getDps(),ohe.getWeaponTypeName(),enchant);
		base.setOH(oh);
		
		//base.setGearBuffs(null);
		
		ItemEquiped item = null;
		for(String name: loader.getEquipment().equipment.keySet()){
			item = loader.getEquipment().get(name);
			base.incStr(item.getStr());
			base.incAgi(item.getAgi());
			base.incHaste(item.getReforgedHaste());
			base.incMastery(item.getReforgedMastery());
			base.incExp(item.getReforgedExp());
			base.incCrit(item.getReforgedCrit());
			base.incHit(item.getReforgedHit());
			
			boolean colorMatch = true;
			for(int j = 0; j < 3;j++){
				if(item.getGem(j) != null){
					base.incAgi(item.getGem(j).getAgi());
					base.incHaste(item.getGem(j).getHaste());
					base.incHit(item.getGem(j).getHit());
					base.incMastery(item.getGem(j).getMastery());
					
					int type = item.getGem(j).getType();
					if(item.gemSlot[j].equals("RED") && (type != Gem.RED && type != Gem.ORANGE && type != Gem.PURPLE)){
						colorMatch = false;
					}
					else if(item.gemSlot[j].equals("YELLOW") && (type != Gem.YELLOW && type != Gem.ORANGE && type != Gem.GREEN)){
						colorMatch = false;
					}
					else if(item.gemSlot[j].equals("BLUE") && (type != Gem.BLUE && type != Gem.PURPLE && type != Gem.GREEN)){
						colorMatch = false;
					}
					else if(item.gemSlot[j].equals("META") && type != Gem.META){
						colorMatch = false;
					}
				}
			}
			if(item.socketBonus != null && colorMatch){
				base.incAgi(item.socketBonus.getAgi());
				base.incHaste(item.socketBonus.getHaste());
				base.incMastery(item.socketBonus.getMastery());
				base.incExp(item.socketBonus.getExp());
				base.incCrit(item.socketBonus.getCrit());
				base.incHit(item.socketBonus.getHit());
			}
			Enchant en = item.getEnchant();
			if(en != null){
				base.incStr(en.getStr());
				base.incAgi(en.getAgi());
				base.incHaste(en.getHaste());
				base.incMastery(en.getMastery());
				base.incExp(en.getExp());
				base.incCrit(en.getCrit());
				base.incHit(en.getHit());
				base.incAp(en.getAp());
			}
			// set item
			if(!item.getSet().equals("")){
				System.out.println(item.getSet());
				base.addSetItem(item.getSet());
			}
			if(item.getGearBuff() != null){
				base.addGearBuff(item.getGearBuff());
			}
		}
		// Race
		String race = base.getRace();
		RaceDB rdb = new RaceDB();
		indzcraft.loader.Race r = rdb.findByName(race);
		if(r != null){
			base.incAgi(r.getAgi());
			base.incStr(r.getStr());
		}
		
		calc = new IndzCraftCalc(loader, base);
		this.dps.setText(""+calc.getDPS());
		log.append("DPS: " + calc.getDPS());
		dpsHistory.add((float) calc.getDPS());
		//createChart();
	}

	public void showEnchantPanel(int slot) {
		enchantPanel = new EnchantPanel(this, slot);
		sidePanel.setViewportView(enchantPanel);
	}
	
	public void showReforgePanel(int slot) {
		reforgePanel = new ReforgePanel(this, slot);
		sidePanel.setViewportView(reforgePanel);
	}
	
	public void createChart(){
		// EXAMPLE CODE START
		dpsHistory.add(30f);
		Iterator<Float> dd = dpsHistory.iterator();
		while(dd.hasNext()){
			System.out.println(dd.next());
		}
        Plot plot = Plots.newPlot(Data.newData(52000, 53000, 52000));
        LineChart chart = GCharts.newLineChart(plot);
        chart.setSize(300, 500);
        //chart.addHorizontalRangeMarker(33.3, 66.6, Color.LIGHTBLUE);
        
        //chart.addXAxisLabels(AxisLabelsFactory.newAxisLabels(Arrays.asList("Peak","Valley"), Arrays.asList(33.3,66.6)));
        //chart.addYAxisLabels(AxisLabelsFactory.newNumericAxisLabels(0,33.3,66.6,100));
        String url = chart.toURLString();
        System.out.println(url);
        JFrame frame = new JFrame();
        JLabel label = null;
		try {
			label = new JLabel(new ImageIcon(ImageIO.read(new URL(url))));
		} catch (MalformedURLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
        frame.getContentPane().add(label, BorderLayout.CENTER);
        frame.pack();
        frame.setVisible(true);
	}
	
	public Log getLog(){
		return log;
	}
	
	public Settings getSettings(){
		return settings;
	}
}
